package com.sptan.framework.mybatis.page;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.Data;

import java.io.Serializable;
import java.util.Optional;

/**
 * The type Page req.
 *
 * @author lp
 */
@Data
public class PageCriteria implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * The constant DESC.
     */
    public static final String DESC = "desc";
    /**
     * The constant ASC.
     */
    public static final String ASC = "asc";
    private final static String[] KEYWORDS = {
        "master",
        "truncate",
        "insert",
        "select",
        "delete",
        "update",
        "declare",
        "alter",
        "drop",
        "sleep"
    };

    private Integer pageNumber = 1;

    private Integer pageSize = 10;

    private String sortBy;

    private String order;

    /**
     * To page page.
     *
     * @param <T> the type parameter
     * @return the page
     */
    public <T> IPage<T> toPage() {
        return PageCriteria.toPage(this);
    }

    /**
     * To page page.
     *
     * @param <T>  the type parameter
     * @param page the page
     * @return the page
     */
    public static <T> IPage<T> toPage(PageCriteria page) {
        Page<T> mybatisPage = null;
        int pageNumber = Optional.ofNullable(page.getPageNumber()).orElse(1);
        int pageSize = Optional.ofNullable(page.getPageSize()).orElse(10);
        String sortBy = page.getSortBy();
        String order = page.getOrder();
        sqlinject(sortBy);
        if (pageNumber < 1) {
            pageNumber = 1;
        }
        if (pageSize < 1) {
            pageSize = 10;
        }
        if (StringUtils.isNotBlank(sortBy)) {
            boolean isAsc = false;
            if (StringUtils.isBlank(order)) {
                isAsc = false;
            } else {
                if (DESC.equals(order.toLowerCase())) {
                    isAsc = false;
                } else if (ASC.equals(order.toLowerCase())) {
                    isAsc = true;
                }
            }
            mybatisPage = new Page<>(pageNumber, pageSize);
            if (isAsc) {
                mybatisPage.addOrder(OrderItem.asc(camel2Underline(sortBy)));
            } else {
                mybatisPage.addOrder(OrderItem.desc(camel2Underline(sortBy)));
            }
        } else {
            mybatisPage = new Page<>(pageNumber, pageSize);
        }
        return mybatisPage;
    }


    /**
     * 驼峰法转下划线.
     *
     * @param str 字符串.
     * @return 返回. string
     */
    public static String camel2Underline(String str) {
        if (StringUtils.isBlank(str)) {
            return "";
        }
        if (str.length() == 1) {
            return str.toLowerCase();
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i < str.length(); i++) {
            if (Character.isUpperCase(str.charAt(i))) {
                sb.append("_" + Character.toLowerCase(str.charAt(i)));
            } else {
                sb.append(str.charAt(i));
            }
        }
        return (str.charAt(0) + sb.toString()).toLowerCase();
    }

    /**
     * 防Mybatis-Plus order by注入.
     *
     * @param param 参数.
     */
    public static void sqlinject(String param) {
        if (StringUtils.isBlank(param)) {
            return;
        }
        // 转换成小写
        param = param.toLowerCase();
        // 判断是否包含非法字符
        for (String keyword : KEYWORDS) {
            if (param.contains(keyword)) {
                throw new RuntimeException(param + "包含非法字符");
            }
        }
    }
}
